// Copyright © SixtyFPS GmbH <info@slint.dev>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0

import { Button, VerticalBox } from "std-widgets.slint";
export component TestCase inherits Rectangle {
    width: 400phx;
    height: 400phx;

    VerticalLayout {
        fs1 := FocusScope {
            focus-changed-event(reason) => {
                root.scope-focus-reason = reason;
            }
        }

        fs2 := FocusScope { }
    }

    popup := PopupWindow { }

    public function show-popup() {
        popup.show();
    }

    public function focus-fs1() {
        fs1.focus();
    }

    public function focus-fs2() {
        fs2.focus();
    }

    out property <bool> scope-has-focus: fs1.has-focus;
    out property <FocusReason> scope-focus-reason;
}

/*
```rust
use slint::platform::WindowEvent;
use slint::private_unstable_api::re_exports::FocusReason;

let instance = TestCase::new().unwrap();

// gain focus from tabbing
slint_testing::send_keyboard_string_sequence(&instance, "\t");
assert!(instance.get_scope_has_focus());
assert_eq!(instance.get_scope_focus_reason(), FocusReason::TabNavigation);

// lose focus from tabbing
slint_testing::send_keyboard_string_sequence(&instance, "\t");
assert!(!instance.get_scope_has_focus());

// gain focus from clicking
slint_testing::send_mouse_click(&instance, 5., 5.);
assert!(instance.get_scope_has_focus());
assert_eq!(instance.get_scope_focus_reason(), FocusReason::PointerClick);

// lose focus from clicking
slint_testing::send_mouse_click(&instance, 5., 300.);
assert!(!instance.get_scope_has_focus());
assert_eq!(instance.get_scope_focus_reason(), FocusReason::PointerClick);

// tab to refocus for further testing
slint_testing::send_keyboard_string_sequence(&instance, "\t");
assert!(instance.get_scope_has_focus());

// lose focus from popup
instance.invoke_show_popup();
assert!(!instance.get_scope_has_focus());
assert_eq!(instance.get_scope_focus_reason(), FocusReason::PopupActivation);

// gain focus from closing popup
slint_testing::send_mouse_click(&instance, 5., 5.);
assert!(instance.get_scope_has_focus());
assert_eq!(instance.get_scope_focus_reason(), FocusReason::PopupActivation);

// lose focus from built-in function
instance.invoke_focus_fs2();
assert!(!instance.get_scope_has_focus());
assert_eq!(instance.get_scope_focus_reason(), FocusReason::Programmatic);

// gain focus from built-in function
instance.invoke_focus_fs1();
assert!(instance.get_scope_has_focus());
assert_eq!(instance.get_scope_focus_reason(), FocusReason::Programmatic);

// lose focus from alt-tabbing
instance.window().dispatch_event(WindowEvent::WindowActiveChanged(false));
assert!(!instance.get_scope_has_focus());
assert_eq!(instance.get_scope_focus_reason(), FocusReason::WindowActivation);

// gain focus from alt-tabbing
instance.window().dispatch_event(WindowEvent::WindowActiveChanged(true));
assert!(instance.get_scope_has_focus());
assert_eq!(instance.get_scope_focus_reason(), FocusReason::WindowActivation);
```

```cpp
using slint::cbindgen_private::FocusReason;

auto handle = TestCase::create();
const TestCase &instance = *handle;

// gain focus from tabbing
slint_testing::send_keyboard_string_sequence(&instance, "\t");
assert(instance.get_scope_has_focus());
assert(instance.get_scope_focus_reason() == FocusReason::TabNavigation);

// lose focus from tabbing
slint_testing::send_keyboard_string_sequence(&instance, "\t");
assert(!instance.get_scope_has_focus());

// gain focus from clicking
slint_testing::send_mouse_click(&instance, 5., 5.);
assert(instance.get_scope_has_focus());
assert(instance.get_scope_focus_reason() == FocusReason::PointerClick);

// lose focus from clicking
slint_testing::send_mouse_click(&instance, 5., 300.);
assert(!instance.get_scope_has_focus());
assert(instance.get_scope_focus_reason() == FocusReason::PointerClick);

// tab to refocus for further testing
slint_testing::send_keyboard_string_sequence(&instance, "\t");
assert(instance.get_scope_has_focus());

// lose focus from popup
instance.invoke_show_popup();
assert(!instance.get_scope_has_focus());
assert(instance.get_scope_focus_reason() == FocusReason::PopupActivation);

// gain focus from closing popup
slint_testing::send_mouse_click(&instance, 5., 5.);
assert(instance.get_scope_has_focus());
assert(instance.get_scope_focus_reason() == FocusReason::PopupActivation);

// lose focus from built-in function
instance.invoke_focus_fs2();
assert(!instance.get_scope_has_focus());
assert(instance.get_scope_focus_reason() == FocusReason::Programmatic);

// gain focus from built-in function
instance.invoke_focus_fs1();
assert(instance.get_scope_has_focus());
assert(instance.get_scope_focus_reason() == FocusReason::Programmatic);

// lose focus from alt-tabbing
instance.window().dispatch_window_active_changed_event(false);
assert(!instance.get_scope_has_focus());
assert(instance.get_scope_focus_reason() == FocusReason::WindowActivation);

// gain focus from alt-tabbing
instance.window().dispatch_window_active_changed_event(true);
assert(instance.get_scope_has_focus());
assert(instance.get_scope_focus_reason() == FocusReason::WindowActivation);
```
*/
